/*
 * @(#)BizBusinessServiceImpl.java 2020年1月6日 下午3:38:49
 * Copyright 2020 zmr, Inc. All rights reserved. 
 * PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.ruoyi.activiti.service.impl;

import com.ruoyi.activiti.consts.ActivitiConstant;
import com.ruoyi.activiti.context.FlowContext;
import com.ruoyi.activiti.domain.BizAudit;
import com.ruoyi.activiti.domain.BizBusiness;
import com.ruoyi.activiti.mapper.BizBusinessMapper;
import com.ruoyi.activiti.service.IBizAuditService;
import com.ruoyi.activiti.service.IBizBusinessService;
import com.ruoyi.activiti.service.IBizNodeService;
import com.ruoyi.activiti.engine.IBaseFlowService;
import com.ruoyi.common.core.redis.RedisIdGenerator;
import com.ruoyi.common.utils.StringUtils;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>File：BizBusinessServiceImpl.java</p>
 * <p>Title: </p>
 * <p>Description:</p>
 * <p>Copyright: Copyright (c) 2020 2020年1月6日 下午3:38:49</p>
 * <p>Company: zmrit.com </p>
 * @author zmr
 * @version 1.0
 */
@Service
public class BizBusinessServiceImpl implements IBizBusinessService
{
    @Autowired
    private BizBusinessMapper businessMapper;

    @Autowired
    private RuntimeService    runtimeService;

    @Autowired
    private IdentityService   identityService;

    @Autowired
    private TaskService       taskService;
    
    @Autowired
    private IBizNodeService   bizNodeService;
    
    @Autowired
    private RedisIdGenerator redisIdGenerator;
    
    @Autowired
    private IBizAuditService bizAuditService;
    
    @Autowired
    private FlowContext flowContext;
    
    

    /**
     * 查询流程业务
     * 
     * @param id 流程业务ID
     * @return 流程业务
     */
    @Override
    public BizBusiness selectBizBusinessById(String id)
    {
        return businessMapper.selectBizBusinessById(Long.valueOf(id));
    }

    /**
     * 查询流程业务列表
     * 
     * @param bizBusiness 流程业务
     * @return 流程业务
     */
    @Override
    public List<BizBusiness> selectBizBusinessList(BizBusiness bizBusiness)
    {
        return businessMapper.selectBizBusinessList(bizBusiness);
    }

    /**
     * 新增流程业务
     * 
     * @param bizBusiness 流程业务
     * @return 结果
     */
    @Override
    public int insertBizBusiness(BizBusiness bizBusiness)
    {
    	bizBusiness.setId(redisIdGenerator.generatorBizId());
        return businessMapper.insertBizBusiness(bizBusiness);
    }

    /**
     * 修改流程业务
     * 
     * @param bizBusiness 流程业务
     * @return 结果
     */
    @Override
    public int updateBizBusiness(BizBusiness bizBusiness)
    {
        return businessMapper.updateBizBusiness(bizBusiness);
    }

    /**
     * 删除流程业务对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteBizBusinessByIds(String ids)
    {
    	Long[] idsArr = StringUtils.str2List(ids, ",", true, true)
    			.stream()
    			.map(s -> Long.valueOf(s))
    			.toArray(Long[]::new);
    	
        return businessMapper.deleteBizBusinessByIds(idsArr);
    }

	
    /**
     * 删除流程业务信息
     * 
     * @param id 流程业务ID
     * @return 结果
     */
    public int deleteBizBusinessById(Long id)
    {
        return businessMapper.deleteBizBusinessById(id);
    }

    /* (non-Javadoc)
     * @see com.ruoyi.activiti.service.IBizBusinessService#deleteBizBusinessLogic(java.lang.String)
     */
    @Override
    public int deleteBizBusinessLogic(String ids)
    {
    	StringUtils.str2List(ids, ",", true, true)
		.stream()
		.forEach(s -> {
			businessMapper.updateBizBusiness(new BizBusiness().setDelFlag(true).setId(Long.parseLong(s)));
		});
    	return 1;
    }

    /* (non-Javadoc)
     * @see com.ruoyi.activiti.service.IBizBusinessService#startProcess(com.ruoyi.activiti.domain.BizBusiness, java.util.Map)
     */
    @Override
    public void startProcess(BizBusiness business, Map<String, Object> variables)
    {
        // 启动流程用户
        identityService.setAuthenticatedUserId(business.getUserId().toString());
        // 启动流程 需传入业务表id变量
        ProcessInstance pi = runtimeService.startProcessInstanceById(business.getProcDefId(),
                business.getId().toString(), variables);
        // 设置流程实例名称
//        runtimeService.setProcessInstanceName(pi.getId(), "");
      
//        BizBusiness bizBusiness = new BizBusiness().setId(business.getId()).setProcInstId(pi.getId())
//                .setProcDefKey(pi.getProcessDefinitionKey());
        // 假如开始就没有任务，那就认为是中止的流程，通常是不存在的
//        setAuditor(bizBusiness.getProcInstId(), bizBusiness, ActivitiConstant.RESULT_SUSPEND, business.getUserId());
    }

    public void suspend(String signalName, String executionId) {
        runtimeService.signalEventReceived(signalName);
    }

    /**
     * 根据流程实例ID，手动触发信号事件
     *
     * @param signalName
     * @param processDefKey
     * @param businessKey
     */
    @Override
    public void suspendByBusinesskey(String signalName, String processDefKey, String businessKey) {
        List<Execution> list = runtimeService.createExecutionQuery()
                .signalEventSubscriptionName(signalName)
                .processInstanceBusinessKey(businessKey)
                .processDefinitionKey(processDefKey)
                .list();
        if (list != null && !list.isEmpty())
            list.forEach(ec -> {
                suspend(signalName, ec.getId());
            });
    }

    /* (non-Javadoc)
     * @see com.ruoyi.activiti.service.IBizBusinessService#audit(com.ruoyi.activiti.domain.BizAudit)
     */
    @Override
    @Transactional(rollbackFor=Exception.class)
    public void audit(BizAudit bizAudit, Long auditorId, String auditor)
    {
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("result", bizAudit.getResult());
        // 处理业务
        String taskDefKey = bizAudit.getTaskDefKey();
        IBaseFlowService tskService = flowContext.get(taskDefKey);
        int result = tskService.execTsk(bizAudit);

        // 审批
        if (result == 1) {
            taskService.complete(bizAudit.getTaskId(), variables);
            bizAudit.setAuditorId(auditorId);
            bizAudit.setAuditor(auditor);
            bizAuditService.insertBizAudit(bizAudit);
        }
        // 以下转移到 com.ruoyi.activiti.listener.MyExecutionListener 实现
//        BizBusiness bizBusiness = new BizBusiness().setId(bizAudit.getBusinessKey())
//                .setProcInstId(bizAudit.getProcInstId());
        
//        setAuditor(bizBusiness.getProcInstId(), bizBusiness, bizAudit.getResult(), auditorId);
    }

    @Override
    public int setAuditor(String procInstId, BizBusiness business, int result, long currentUserId)
    {
        List<Task> tasks = taskService.createTaskQuery()
        		.processInstanceBusinessKey(business.getId() + "")
        		//.processInstanceId(procInstId)
        		.list();
        if (null != tasks && tasks.size() > 0)
        {
            Task task = tasks.get(0);
            //Set<String> auditors = bizNodeService.getAuditors(task.getTaskDefinitionKey(), currentUserId);
            List<String> auditors = new ArrayList<String>(0);
            // 从业务中获取配置的审核候选人
            IBaseFlowService tskService = flowContext.get(task.getTaskDefinitionKey());
            if (tskService != null) {
            	auditors = tskService.getAuditors(business.getId() + "");
            }
            // 从全局配置中获取审核候选人
            if (auditors.isEmpty()) {
            	Set<String> theauditors = bizNodeService.getAuditors(task.getTaskDefinitionKey(), currentUserId);
            	auditors = theauditors.stream().collect(Collectors.toList());
            }
            if (null != auditors && auditors.size() > 0)
            {
                // 添加审核候选人
                for (String auditor : auditors)
                {
                    taskService.addCandidateUser(task.getId(), auditor);
                }
                business.setCurrentTask(task.getName());
            }
            else
            {
                runtimeService.deleteProcessInstance(task.getProcessInstanceId(),
                        ActivitiConstant.SUSPEND_PRE + "no auditor");
                business.setCurrentTask(ActivitiConstant.END_TASK_NAME).setStatus(ActivitiConstant.STATUS_SUSPEND)
                        .setResult(ActivitiConstant.RESULT_SUSPEND);
            }
        }
        // 如果都没有任务
        if (tasks == null || tasks.isEmpty())
        {
        	
            // 任务结束
            business.setCurrentTask(ActivitiConstant.END_TASK_NAME).setStatus(ActivitiConstant.STATUS_FINISH)
                    .setResult(result);
        }
        return updateBizBusiness(business);
    }
}
